/*
 * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
 *
 * Copyright (C) 2002-2011 Aleph One Ltd.
 *   for Toby Churchill Ltd and Brightstar Engineering
 *
 * Created by Charles Manning <charles@aleph1.co.uk>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

/*
 * yaffscfg2k.c  The configuration for the "direct" use of yaffs.
 *
 * This file is intended to be modified to your requirements.
 * There is no need to redistribute this file.
 */

#include "yaffscfg.h"
#include "yaffs_guts.h"
#include "yaffsfs.h"
#include "yaffs_fileem2k.h"
#include "yaffs_nandemul2k.h"
#include "yaffs_trace.h"
#include "yaffs_osglue.h"


#include <errno.h>
#include <iosLib.h>

unsigned yaffs_trace_mask =

	YAFFS_TRACE_SCAN |
	YAFFS_TRACE_GC |
	YAFFS_TRACE_ERASE |
	YAFFS_TRACE_ERROR |
	YAFFS_TRACE_TRACING |
	YAFFS_TRACE_ALLOCATE |
	YAFFS_TRACE_BAD_BLOCKS |
	YAFFS_TRACE_VERIFY |
	0;



/* Configure the devices that will be used */

#include "yaffs_flashif2.h"

extern int yaffs_test_init(void);

int yaffsDrvNum = -1;
DEV_HDR yaffsDevHdr;


int yaffsCreate(DEV_HDR *pDevHdr, char *fileName, int mode)
{
    char name[NAME_MAX];
    
    yaffs_trace(YAFFS_TRACE_DEBUG, "<%s-%d> dev(%d-%s): file %s, mode %d\n",
        __FUNCTION__, __LINE__, pDevHdr->drvNum, pDevHdr->name, fileName, mode);
    
    sprintf(name, "/yaffs2/%s", fileName);
    
    return yaffs_open(name, O_CREAT | O_RDWR, S_IREAD | S_IWRITE);
}

int yaffsDelete(DEV_HDR *pDevHdr, char *fileName)
{
    char name[NAME_MAX];
    
    yaffs_trace(YAFFS_TRACE_DEBUG, "<%s-%d> dev(%d-%s): file %s\n",
        __FUNCTION__, __LINE__, pDevHdr->drvNum, pDevHdr->name, fileName);
    sprintf(name, "/yaffs2/%s", fileName);
    
    return yaffs_unlink(name);
}

int yaffsOpen(DEV_HDR *pDevHdr, char *fileName, int flags, int mode)
{
    char name[NAME_MAX];
    yaffs_trace(YAFFS_TRACE_DEBUG, "<%s-%d> dev(%d-%s): file %s, flags %d, mode %d\n",
        __FUNCTION__, __LINE__, pDevHdr->drvNum, pDevHdr->name, fileName, flags, mode);
    sprintf(name, "/yaffs2/%s", fileName);
    
    if (flags & O_CREAT
        && mode & FSTAT_DIR) {
        return yaffs_mkdir(name, mode);
    }
    
    return yaffs_open(name, flags, mode);
}

int yaffsClose(int fd)
{
    yaffs_trace(YAFFS_TRACE_DEBUG, "<%s-%d> fd %d\n",
        __FUNCTION__, __LINE__, fd);
    return yaffs_close(fd);
}

int yaffsRead(int fd, char *buffer, int maxbytes)
{
    yaffs_trace(YAFFS_TRACE_DEBUG, "<%s-%d> fd %d, buffer %p, maxbytes %d\n",
        __FUNCTION__, __LINE__, fd, buffer, maxbytes);
    return yaffs_read(fd, buffer, maxbytes);
}

int yaffsWrite(int fd, char *buffer, int maxbytes)
{
    yaffs_trace(YAFFS_TRACE_DEBUG, "<%s-%d> fd %d, buffer %p, maxbytes %d\n",
        __FUNCTION__, __LINE__, fd, buffer, maxbytes);
    return yaffs_write(fd, buffer, maxbytes);
}

int yaffsIoctl(int fd, int function, int arg)
{
    int rv = 0;
    
    struct yaffs_stat stat_buf;
    
    memset(&stat_buf, 0, sizeof(yaffs_stat));
    
    yaffs_trace(YAFFS_TRACE_DEBUG, "<%s-%d> fd %d, function %d, arg %d\n",
        __FUNCTION__, __LINE__, fd, function, arg);
    
    switch (function) {
        case FIOFSTATGET:
            rv = yaffs_fstat(fd, &stat_buf);
            memcpy((struct yaffs_stat *)arg, &stat_buf, sizeof(yaffs_stat));
            break;
        case FIOTIMESET:
            rv = yaffs_futime(fd, (struct yaffs_utimbuf *)arg);
            break;
        default:
            break;
    }
    
    return rv;
}

int yaffsDrvinit()
{
    if (yaffsDrvNum != -1)
        return 0;
    
    yaffsDrvNum = iosDrvInstall(yaffsCreate,
                        yaffsDelete,
                        yaffsOpen,
                        yaffsClose,
                        yaffsRead,
                        yaffsWrite,
                        yaffsIoctl);
    if (yaffsDrvNum == -1) {
        printf("\niosDrvInstall yaffs2 failed\n");
        return -1;
    }
    
    if (iosDevAdd(&yaffsDevHdr, "/yaffs2", yaffsDrvNum)) {
        printf("\niosDevAdd /yaffs2 failed\n");
        return -1;
    }
    
    return 0;
}


int yaffs_start_up(void)
{
    int output = 0;
    static int start_up_called = 0;

    if(start_up_called)
        return 0;
    start_up_called = 1;

    yaffs_set_trace(0);

    /* Call the OS initialisation (eg. set up lock semaphore */
    yaffsfs_OSInitialisation();

    /* Install the various devices and their device drivers */
    yflash2_install_drv("yaffs2");
    output = yaffs_mount("/yaffs2");

    if (output >= 0) {  
        printf("\nyaffs mounted: /yaffs2\n"); 
    } else {
        printf("\nyaffs failed to mount: /yaffs2\n");
        return -1;
    }

    if (yaffsDrvinit())
        return -1;

    yaffs_test_init();

    return 0;
}


